package com.soft.zosagent.util;


import com.soft.zosagent.common.Constant;
import com.soft.zosagent.pojo.ZFileInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @description: 传输工具util
 * @author: cinbo，chenyinbo
 * @create: 2020-12-08 10:09
 */
public class AgentToolUtil {
    public static  boolean isZosSystem() {
        if(System.getProperty("os.arch").contains("s390") || System.getProperty("os.name").contains("z/OS")) {
            //如果本机是ZOS主机。则需要对，local文件进行初始化，无论是下载还是上传。
            return true;
        }else {
            return false;
        }
    }

    public static void parseDsnameAndMember(ZFileInfo zFileInfo) throws Exception{
        String fileName = zFileInfo.getFileName().trim();
        if(fileName.matches(Constant.ZOSFILEPARTEN1)){
            zFileInfo.setDsname(fileName);
        }else if(fileName.matches(Constant.ZOSFILEPARTEN2)){
            zFileInfo.setDsname(fileName.substring(0,fileName.indexOf("(")));
             zFileInfo.setMember(fileName.substring(fileName.indexOf("(")+1,fileName.length()-1));
        }else{
            throw new RuntimeException("Dataset["+fileName+"] Name is invalid");
        }



    }

    public static List<String> getSplitStringByCommaRecursive(String parmString){
        StringBuffer oneparm = new StringBuffer();
        if(parmString.length() == 0){
            return new ArrayList<>();
        }

        int leftParenttheses=0;

        int singleQuote=0;

        int i=0;
        for(;i<parmString.length();i++){
            char tChar = parmString.charAt(i);
            if(tChar == ',' && leftParenttheses == 0 && singleQuote%2==0)
            {
                break;
            }else{
                oneparm.append(tChar);
            }
            if(tChar=='('){
                leftParenttheses++;
            }
            if(tChar == ')'){
                leftParenttheses--;
            }
            if(tChar == '\''){
                singleQuote++;
            }
        }
        List<String> parmList = new ArrayList<>();
        parmList.add(oneparm.toString());

        if(i+1>=parmString.length()){
            return parmList;
        }else{
            String leftParmString = parmString.substring(i+1);
            parmList.addAll(getSplitStringByCommaRecursive(leftParmString));
        }

        return parmList;
    }

    public static List<String> readListStringFromFile(String filePath){
        List<String> jcllines = new ArrayList<String>();
        try {
            File jclFile1 = new File(filePath);
            FileReader fileReader = new FileReader(jclFile1);
            BufferedReader bufferedReader = new BufferedReader( fileReader );

            String line = null;

            do{
                line = bufferedReader.readLine();

                if(line != null){
                    jcllines.add(line);
                }
            }while(line!=null);
            fileReader.close();
            bufferedReader.close();
        }catch (Exception e){

        }
        return jcllines;
    }

    public static ByteBuf allocNettyHeapByteBuf(ByteBufAllocator bufAllocator,int initSize){

        ByteBuf buf = bufAllocator.heapBuffer(initSize);
        return buf;
    }

    public static ByteBuf allocNettyHeapByteBuf(ByteBufAllocator bufAllocator,int initSize,int maxSize){

        ByteBuf buf = bufAllocator.heapBuffer(initSize,maxSize);
        return buf;
    }
    public static List<String> readJclFileLines(String filePath){

        String encode = getFileCharset(new File(filePath));
        return readListStringFromFile(filePath,encode);
    }

    public static void printCharsetList(){

        Set names= Charset.availableCharsets().keySet();
        for (Iterator iter = names.iterator(); iter.hasNext();) {
            String charsetName = (String) iter.next();
            if(Charset.isSupported(charsetName)){
                System.out.println(charsetName);
            }
        }
    }

    public static List<String> readListStringFromFile(String filePath,String encodeStr){
        List<String> jcllines = new ArrayList<String>();
        try {
            FileInputStream fileInputStream = new FileInputStream(filePath);
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,encodeStr);
            BufferedReader bufferedReader = new BufferedReader( inputStreamReader );

            String line = null;

            do{
                line = bufferedReader.readLine();

                if(line != null){
                    jcllines.add(line);
                }
            }while(line!=null);
            fileInputStream.close();
            inputStreamReader.close();
            bufferedReader.close();
        }catch (Exception e){

        }
        return jcllines;
    }

    /**
     * 获取文件的编码格式
     *
     * @param sourceFile
     * @return
     */
    private static String getFileCharset(File sourceFile) {
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        try {
            boolean checked = false;
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
            bis.mark(0);
            int read = bis.read(first3Bytes, 0, 3);
            if (read == -1) {
                return charset; // 文件编码为 ANSI
            } else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
                charset = "UTF-16LE"; // 文件编码为 Unicode
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) {
                charset = "UTF-16BE"; // 文件编码为 Unicode big endian
                checked = true;
            } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB
                    && first3Bytes[2] == (byte) 0xBF) {
                charset = "UTF-8"; // 文件编码为 UTF-8
                checked = true;
            }
            bis.reset();
            if (!checked) {
                int loc = 0;
                while ((read = bis.read()) != -1) {
                    loc++;
                    if (read >= 0xF0)
                        break;
                    if (0x80 <= read && read <= 0xBF) // 单独出现BF以下的，也算是GBK
                        break;
                    if (0xC0 <= read && read <= 0xDF) {
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) // 双字节 (0xC0 - 0xDF)
                            // (0x80
                            // - 0xBF),也可能在GB编码内
                            continue;
                        else
                            break;
                    } else if (0xE0 <= read && read <= 0xEF) {// 也有可能出错，但是几率较小
                        read = bis.read();
                        if (0x80 <= read && read <= 0xBF) {
                            read = bis.read();
                            if (0x80 <= read && read <= 0xBF) {
                                charset = "UTF-8";
                                break;
                            } else
                                break;
                        } else
                            break;
                    }
                }
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return charset;
    }
    public static String checkFileType(String filePath){

        if (filePath.matches(".*/.*") && !filePath.contains(":")) {
//			if (!filePath.startsWith("/")) {
//				throw new RuntimeException("not a valid unix fileName");
//			} else {
            return Constant.UNIX_FILE;
            //}
        } else if (filePath.matches(".*:/.*")
                || filePath.matches(".*:\\.*")
                || filePath.matches("\\.\\\\.*")
                || filePath.matches(".*:\\\\.*")
        ) {
            //windows file
            return Constant.WINDOWS_FILE;

        } else if (filePath.matches(Constant.ZOSFILEPARTEN1) || filePath.matches(Constant.ZOSFILEPARTEN2)) {
            //zos 文件
            return Constant.ZOS_FILE;
        } else {
            throw new RuntimeException("not support fileName. [" + filePath + "]");
        }
    }

}
